/**
 * @(#)EnlaceHibernateAnnotations.java Mar 1, 2007
 *
 * Copyright (c) 2005-2010 Psiqueware S.A. de C.V. All Rights Reserved.
 * This software is the proprietary information Psiqueware S.A. de C.V.
 * Use is subject to license terms.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * <br/>Usuario : AngelElectrico
 * <br/>Creaci&oacute;n: Mar 1, 2007 - 4:17:28 PM
 * <br/>
 * <br/>
 * <br/><t5>Cambios :</t5>
 * <br/><b>Fecha | Autor  |  Cambios</b>
 * <ul>
 * <li>Mar 1, 2007 | <a href = "mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a> | Creaci&oacute;n del Objeto.</li>
 *
 * </ul>
 * /

 package com.psiqueware.basico.dao.hibernate;

 import com.psiqueware.alheli.basico.InicializacionFallidaException;
 import com.psiqueware.alheli.exception.NullArgumentException;
 import com.psiqueware.alheli.exception.NullPostConditionException;
 import com.psiqueware.alheli.dao.EnlaceTransaccional;
 import com.psiqueware.alheli.logging.Logger;
 import com.psiqueware.alheli.logging.LoggerFactory;
 import org.hibernate.HibernateException;
 import org.hibernate.Session;
 import org.hibernate.SessionFactory;
 import org.hibernate.Transaction;
 //import org.hibernate.cfg.AnnotationConfiguration;

 import java.net.URL;

 /**
 * Enlace transaccional para utilizar Hibernate con Anotaciones.
 * <br/>Paquete Original: com.psiqueware.basico.dao.hibernate
 * <br/>Nombre  Original: EnlaceHibernateAnnotations
 * <br/>Oprima para ver : <a href="EnlaceHibernateAnnotations.java.html"><i>C&oacute;digo Fuente</i> </a>
 *
 * @author <a href="mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a>
 * @version Revision: 1.1 Mar 1, 2007 4:17:28 PM
 * /
public final class EnlaceHibernateAnnotations implements EnlaceTransaccional
{

/** Logger de clase para EnlaceHibernateAnnotations * /
private static final Logger s_log = LoggerFactory.getLogger ( EnlaceHibernateAnnotations.class );

/** F&aacute;brica de Sessiones. * /
private static SessionFactory sessionFactory;

/** Configuraci&oacute;n. * /
private static AnnotationConfiguration configuration;

/** N&uacute;mero de transacciones realizadas. * /
private int m_noTransacciones;

static
{
rebuildSessionFactory ();
}

public static void rebuildSessionFactory ()
{

try
{
ClassLoader classLoader = EnlaceHibernateAnnotations.class.getClassLoader ();
URL url = classLoader.getResource ( "hibernate.cfg.xml" );
configuration = new AnnotationConfiguration ();
configuration.configure ( url );
//            configuration.addClass ( UsuarioPrueba.class );
/*

configuration
.setProperty ( "hibernate.dialect", "org.hibernate.dialect.OracleDialect" )
.setProperty ( "hibernate.connection.driver_class", "oracle.jdbc.driver.OracleDriver" )
.setProperty ( "hibernate.connection.url", "jdbc:oracle:thin:@localhost:1521:XE" )
.setProperty ( "hibernate.connection.username", "UsuarioPruebas" )
.setProperty ( "hibernate.connection.password", "UsuarioPruebas" )
.setProperty ( "hibernate.connection.autocommit", "False" )
.addClass ( UsuarioPruebaK.class );       * /
sessionFactory = configuration.buildSessionFactory ();
}
catch ( HibernateException e )
{
final String error = "<error><msg>No se pudo crear la F&aacute;brica de Sessiones.</msg><error>";
s_log.error ( error );
s_log.error ( e );
throw new InicializacionFallidaException ( error, e );
}
}

/**
 * Agrega una clase a la configuraci&oacute;n de Hibernate.
 *
 * @param clazz a agregar.
 * /
public static void addClass ( Class clazz )
{
configuration.addClass ( clazz ).buildSessionFactory ();
sessionFactory = configuration.buildSessionFactory ();
}

/** Sesion utilizada durante este enlace. * /
private Session m_session;

/** Transaccion abierta. * /
private Transaction m_transaction;

/** Constructor de EnlaceHibernateAnnotations. * /
public EnlaceHibernateAnnotations ()
{

}

/**
 * Inicia una transaccion.
 * Es importante cerrar la sessi&oacute;n utilizando el m&eacute;todo this#finalizaTransaccion
 *
 * @noinspection HibernateResourceOpenedButNotSafelyClosed
 * /
public void iniciaTransaccion ()
{
m_session = sessionFactory.openSession ();
m_transaction = m_session.beginTransaction ();
if ( null == m_transaction ) throw new NullPostConditionException ( "<error>A fallado una postcondici&oacute;n. El argumento de salida 'm_transaction' no puede ser NULL.</error>" );
m_transaction.begin ();
if ( !m_transaction.isActive () ) throw new RuntimeException ( "La transacci&oacute;n no se inici&oacute;." );
if ( s_log.isDebugEnabled () ) s_log.debug ( "<msg>Se ha iniciado una transaccion.</msg>" );
}

/**
 * Devuelve el objeto del cual estamos haciendo nuestra transaccion.
 *
 * @return Object para hacerle casting dependiendo nuestra capa de datos.
 * /
public Object continuaTransaccion ()
{
m_noTransacciones++;
if ( null == m_session ) throw new NullArgumentException ( "<error>La 'm_session' es nula, probablemente no se inici&oacute; la transacci&oacute;n.</error>" );
return m_session;
}

/**
 * Finaliza la transaccion, despu&eacute;s de este punto ya no se puede hacer rollback.
 *
 * @noinspection AssignmentToNull
 * /
public void finalizaTransaccion ()
{
if ( s_log.isDebugEnabled () ) s_log.debug ( "<msg>Se pretende ingresar la transaccion.</msg>" );
if ( !m_transaction.wasRolledBack () ){
m_session.flush ();
m_transaction.commit ();
}

m_session.disconnect ();
m_session.close ();
if ( s_log.isDebugEnabled () ) s_log.debug ( "<msg>&Eacute;xito al finalizar la transacci&oacute;n.</msg>" );
}

/** Invoquese si sucede un problema con la transaccion. * /
public void rollBack ()
{
if ( m_transaction.wasCommitted () ) throw new RuntimeException ( "<msg>La Transaccion ya fu&eacute; ingresada a la Base de Datos.</msg>" );
//no es necesario hacerlo 2 veces
if ( !m_transaction.wasRolledBack () ) m_transaction.rollback ();
}

/**
 * Devuelve el n&uacute;mero de transacciones que se llevan realizadas por este {@link EnlaceTransaccional}.
 * Generalmente la implementaci&oacute;n implica contar el n&uacute;mero de veces que se ha llamado a continuaTransaccion.
 *
 * @return n&uacute;mero de transacciones.
 *
 * @see this#continuaTransaccion()
 * /
public int numeroTransacciones ()
{
return m_noTransacciones;
}
}

 */